"""
交易成本分析

提供交易成本计算、分析和优化功能。
"""

from abc import ABC, abstractmethod
from enum import Enum
from typing import Dict, List, Optional, Any, Tuple
from datetime import datetime, timedelta
from dataclasses import dataclass, field
from decimal import Decimal
import math

from .order_manager import Order, OrderSide, OrderType, OrderFill
from .slippage_model import SlippageResult


class CostType(Enum):
    """成本类型枚举"""
    COMMISSION = "commission"  # 佣金
    STAMP_TAX = "stamp_tax"  # 印花税
    TRANSFER_FEE = "transfer_fee"  # 过户费
    SETTLEMENT_FEE = "settlement_fee"  # 结算费
    SLIPPAGE = "slippage"  # 滑点成本
    MARKET_IMPACT = "market_impact"  # 市场冲击成本
    TIMING_COST = "timing_cost"  # 时机成本
    OPPORTUNITY_COST = "opportunity_cost"  # 机会成本


class MarketType(Enum):
    """市场类型枚举"""
    A_SHARE = "a_share"  # A股
    FUTURES = "futures"  # 期货
    ETF = "etf"  # ETF
    BOND = "bond"  # 债券
    OPTION = "option"  # 期权
    FUND = "fund"  # 基金


@dataclass
class CostParams:
    """成本参数"""
    # 佣金参数
    commission_rate: float = 0.0003  # 佣金费率（万分之三）
    min_commission: Decimal = Decimal("5.0")  # 最低佣金
    max_commission: Optional[Decimal] = None  # 最高佣金
    
    # 印花税参数
    stamp_tax_rate: float = 0.001  # 印花税费率（千分之一）
    stamp_tax_on_buy: bool = False  # 买入是否收印花税
    stamp_tax_on_sell: bool = True  # 卖出是否收印花税
    
    # 过户费参数
    transfer_fee_rate: float = 0.00002  # 过户费费率（万分之0.2）
    min_transfer_fee: Decimal = Decimal("1.0")  # 最低过户费
    
    # 结算费参数
    settlement_fee_rate: float = 0.0  # 结算费费率
    settlement_fee_fixed: Decimal = Decimal("0.0")  # 固定结算费
    
    # 市场冲击参数
    market_impact_factor: float = 0.1  # 市场冲击因子
    
    # 时机成本参数
    timing_cost_factor: float = 0.05  # 时机成本因子


@dataclass
class CostBreakdown:
    """成本明细"""
    cost_type: CostType  # 成本类型
    amount: Decimal  # 成本金额
    rate: float  # 成本费率
    description: str  # 成本描述
    calculation_details: Dict[str, Any] = field(default_factory=dict)  # 计算详情


@dataclass
class TransactionCost:
    """交易成本"""
    order_id: str  # 订单ID
    symbol: str  # 标的代码
    side: OrderSide  # 买卖方向
    quantity: Decimal  # 数量
    price: Decimal  # 价格
    market_value: Decimal  # 市值
    
    # 成本明细
    commission: Decimal = Decimal("0")  # 佣金
    stamp_tax: Decimal = Decimal("0")  # 印花税
    transfer_fee: Decimal = Decimal("0")  # 过户费
    settlement_fee: Decimal = Decimal("0")  # 结算费
    slippage_cost: Decimal = Decimal("0")  # 滑点成本
    market_impact_cost: Decimal = Decimal("0")  # 市场冲击成本
    timing_cost: Decimal = Decimal("0")  # 时机成本
    opportunity_cost: Decimal = Decimal("0")  # 机会成本
    
    # 总成本
    total_cost: Decimal = Decimal("0")  # 总成本
    total_rate: float = 0.0  # 总成本率
    
    # 成本明细列表
    cost_breakdown: List[CostBreakdown] = field(default_factory=list)
    
    # 计算时间
    calculated_at: datetime = field(default_factory=datetime.now)


class BaseCostModel(ABC):
    """基础成本模型抽象类"""
    
    def __init__(self, market_type: MarketType, params: CostParams):
        """
        初始化成本模型
        
        Args:
            market_type: 市场类型
            params: 成本参数
        """
        self.market_type = market_type
        self.params = params
    
    @abstractmethod
    def calculate_cost(
        self,
        order: Order,
        fill: Optional[OrderFill] = None,
        slippage_result: Optional[SlippageResult] = None
    ) -> TransactionCost:
        """
        计算交易成本
        
        Args:
            order: 订单信息
            fill: 成交信息
            slippage_result: 滑点结果
            
        Returns:
            TransactionCost: 交易成本
        """
        pass
    
    def _calculate_commission(self, market_value: Decimal) -> Tuple[Decimal, CostBreakdown]:
        """计算佣金"""
        commission = market_value * Decimal(str(self.params.commission_rate))
        
        # 应用最低佣金
        if commission < self.params.min_commission:
            commission = self.params.min_commission
        
        # 应用最高佣金
        if self.params.max_commission and commission > self.params.max_commission:
            commission = self.params.max_commission
        
        breakdown = CostBreakdown(
            cost_type=CostType.COMMISSION,
            amount=commission,
            rate=self.params.commission_rate,
            description=f"佣金费率: {self.params.commission_rate:.4%}",
            calculation_details={
                "market_value": float(market_value),
                "rate": self.params.commission_rate,
                "min_commission": float(self.params.min_commission),
                "max_commission": float(self.params.max_commission) if self.params.max_commission else None
            }
        )
        
        return commission, breakdown
    
    def _calculate_stamp_tax(self, market_value: Decimal, side: OrderSide) -> Tuple[Decimal, Optional[CostBreakdown]]:
        """计算印花税"""
        should_charge = (
            (side == OrderSide.BUY and self.params.stamp_tax_on_buy) or
            (side == OrderSide.SELL and self.params.stamp_tax_on_sell)
        )
        
        if not should_charge:
            return Decimal("0"), None
        
        stamp_tax = market_value * Decimal(str(self.params.stamp_tax_rate))
        
        breakdown = CostBreakdown(
            cost_type=CostType.STAMP_TAX,
            amount=stamp_tax,
            rate=self.params.stamp_tax_rate,
            description=f"印花税费率: {self.params.stamp_tax_rate:.4%}",
            calculation_details={
                "market_value": float(market_value),
                "rate": self.params.stamp_tax_rate,
                "side": side.value,
                "on_buy": self.params.stamp_tax_on_buy,
                "on_sell": self.params.stamp_tax_on_sell
            }
        )
        
        return stamp_tax, breakdown
    
    def _calculate_transfer_fee(self, market_value: Decimal) -> Tuple[Decimal, CostBreakdown]:
        """计算过户费"""
        transfer_fee = market_value * Decimal(str(self.params.transfer_fee_rate))
        
        # 应用最低过户费
        if transfer_fee < self.params.min_transfer_fee:
            transfer_fee = self.params.min_transfer_fee
        
        breakdown = CostBreakdown(
            cost_type=CostType.TRANSFER_FEE,
            amount=transfer_fee,
            rate=self.params.transfer_fee_rate,
            description=f"过户费费率: {self.params.transfer_fee_rate:.6%}",
            calculation_details={
                "market_value": float(market_value),
                "rate": self.params.transfer_fee_rate,
                "min_transfer_fee": float(self.params.min_transfer_fee)
            }
        )
        
        return transfer_fee, breakdown
    
    def _calculate_settlement_fee(self, market_value: Decimal) -> Tuple[Decimal, Optional[CostBreakdown]]:
        """计算结算费"""
        if self.params.settlement_fee_rate == 0 and self.params.settlement_fee_fixed == 0:
            return Decimal("0"), None
        
        settlement_fee = (
            market_value * Decimal(str(self.params.settlement_fee_rate)) +
            self.params.settlement_fee_fixed
        )
        
        breakdown = CostBreakdown(
            cost_type=CostType.SETTLEMENT_FEE,
            amount=settlement_fee,
            rate=self.params.settlement_fee_rate,
            description=f"结算费: {self.params.settlement_fee_rate:.6%} + {self.params.settlement_fee_fixed}",
            calculation_details={
                "market_value": float(market_value),
                "rate": self.params.settlement_fee_rate,
                "fixed_fee": float(self.params.settlement_fee_fixed)
            }
        )
        
        return settlement_fee, breakdown


class AShareCostModel(BaseCostModel):
    """A股成本模型"""
    
    def __init__(self, params: Optional[CostParams] = None):
        """初始化A股成本模型"""
        if params is None:
            # A股默认参数
            params = CostParams(
                commission_rate=0.0003,  # 万分之三
                min_commission=Decimal("5.0"),
                stamp_tax_rate=0.001,  # 千分之一
                stamp_tax_on_buy=False,
                stamp_tax_on_sell=True,
                transfer_fee_rate=0.00002,  # 万分之0.2
                min_transfer_fee=Decimal("1.0")
            )
        super().__init__(MarketType.A_SHARE, params)
    
    def calculate_cost(
        self,
        order: Order,
        fill: Optional[OrderFill] = None,
        slippage_result: Optional[SlippageResult] = None
    ) -> TransactionCost:
        """计算A股交易成本"""
        # 使用成交信息或订单信息
        if fill:
            quantity = fill.quantity
            price = fill.price
        else:
            quantity = order.quantity
            price = order.price or Decimal("0")
        
        market_value = quantity * price
        
        # 计算各项成本
        commission, commission_breakdown = self._calculate_commission(market_value)
        stamp_tax, stamp_tax_breakdown = self._calculate_stamp_tax(market_value, order.side)
        transfer_fee, transfer_fee_breakdown = self._calculate_transfer_fee(market_value)
        settlement_fee, settlement_fee_breakdown = self._calculate_settlement_fee(market_value)
        
        # 滑点成本
        slippage_cost = Decimal("0")
        slippage_breakdown = None
        if slippage_result:
            slippage_cost = slippage_result.slippage_cost
            slippage_breakdown = CostBreakdown(
                cost_type=CostType.SLIPPAGE,
                amount=slippage_cost,
                rate=slippage_result.slippage_rate,
                description=f"滑点成本: {slippage_result.slippage_rate:.4%}",
                calculation_details={
                    "slippage_amount": float(slippage_result.slippage_amount),
                    "slippage_rate": slippage_result.slippage_rate,
                    "model_type": slippage_result.model_type.value
                }
            )
        
        # 总成本
        total_cost = commission + (stamp_tax or Decimal("0")) + transfer_fee + (settlement_fee or Decimal("0")) + slippage_cost
        total_rate = float(total_cost / market_value) if market_value > 0 else 0.0
        
        # 成本明细
        cost_breakdown = [commission_breakdown, transfer_fee_breakdown]
        if stamp_tax_breakdown:
            cost_breakdown.append(stamp_tax_breakdown)
        if settlement_fee_breakdown:
            cost_breakdown.append(settlement_fee_breakdown)
        if slippage_breakdown:
            cost_breakdown.append(slippage_breakdown)
        
        return TransactionCost(
            order_id=order.order_id,
            symbol=order.symbol,
            side=order.side,
            quantity=quantity,
            price=price,
            market_value=market_value,
            commission=commission,
            stamp_tax=stamp_tax or Decimal("0"),
            transfer_fee=transfer_fee,
            settlement_fee=settlement_fee or Decimal("0"),
            slippage_cost=slippage_cost,
            total_cost=total_cost,
            total_rate=total_rate,
            cost_breakdown=cost_breakdown
        )


class FuturesCostModel(BaseCostModel):
    """期货成本模型"""
    
    def __init__(self, params: Optional[CostParams] = None):
        """初始化期货成本模型"""
        if params is None:
            # 期货默认参数
            params = CostParams(
                commission_rate=0.0001,  # 万分之一
                min_commission=Decimal("2.0"),
                stamp_tax_rate=0.0,  # 期货无印花税
                transfer_fee_rate=0.0,  # 期货无过户费
                settlement_fee_rate=0.00001  # 万分之0.1
            )
        super().__init__(MarketType.FUTURES, params)
    
    def calculate_cost(
        self,
        order: Order,
        fill: Optional[OrderFill] = None,
        slippage_result: Optional[SlippageResult] = None
    ) -> TransactionCost:
        """计算期货交易成本"""
        # 使用成交信息或订单信息
        if fill:
            quantity = fill.quantity
            price = fill.price
        else:
            quantity = order.quantity
            price = order.price or Decimal("0")
        
        market_value = quantity * price
        
        # 计算各项成本
        commission, commission_breakdown = self._calculate_commission(market_value)
        settlement_fee, settlement_fee_breakdown = self._calculate_settlement_fee(market_value)
        
        # 滑点成本
        slippage_cost = Decimal("0")
        slippage_breakdown = None
        if slippage_result:
            slippage_cost = slippage_result.slippage_cost
            slippage_breakdown = CostBreakdown(
                cost_type=CostType.SLIPPAGE,
                amount=slippage_cost,
                rate=slippage_result.slippage_rate,
                description=f"滑点成本: {slippage_result.slippage_rate:.4%}",
                calculation_details={
                    "slippage_amount": float(slippage_result.slippage_amount),
                    "slippage_rate": slippage_result.slippage_rate,
                    "model_type": slippage_result.model_type.value
                }
            )
        
        # 总成本
        total_cost = commission + (settlement_fee or Decimal("0")) + slippage_cost
        total_rate = float(total_cost / market_value) if market_value > 0 else 0.0
        
        # 成本明细
        cost_breakdown = [commission_breakdown]
        if settlement_fee_breakdown:
            cost_breakdown.append(settlement_fee_breakdown)
        if slippage_breakdown:
            cost_breakdown.append(slippage_breakdown)
        
        return TransactionCost(
            order_id=order.order_id,
            symbol=order.symbol,
            side=order.side,
            quantity=quantity,
            price=price,
            market_value=market_value,
            commission=commission,
            settlement_fee=settlement_fee or Decimal("0"),
            slippage_cost=slippage_cost,
            total_cost=total_cost,
            total_rate=total_rate,
            cost_breakdown=cost_breakdown
        )


class ETFCostModel(BaseCostModel):
    """ETF成本模型"""
    
    def __init__(self, params: Optional[CostParams] = None):
        """初始化ETF成本模型"""
        if params is None:
            # ETF默认参数
            params = CostParams(
                commission_rate=0.0003,  # 万分之三
                min_commission=Decimal("5.0"),
                stamp_tax_rate=0.0,  # ETF无印花税
                transfer_fee_rate=0.00002,  # 万分之0.2
                min_transfer_fee=Decimal("1.0")
            )
        super().__init__(MarketType.ETF, params)
    
    def calculate_cost(
        self,
        order: Order,
        fill: Optional[OrderFill] = None,
        slippage_result: Optional[SlippageResult] = None
    ) -> TransactionCost:
        """计算ETF交易成本"""
        # 使用成交信息或订单信息
        if fill:
            quantity = fill.quantity
            price = fill.price
        else:
            quantity = order.quantity
            price = order.price or Decimal("0")
        
        market_value = quantity * price
        
        # 计算各项成本
        commission, commission_breakdown = self._calculate_commission(market_value)
        transfer_fee, transfer_fee_breakdown = self._calculate_transfer_fee(market_value)
        
        # 滑点成本
        slippage_cost = Decimal("0")
        slippage_breakdown = None
        if slippage_result:
            slippage_cost = slippage_result.slippage_cost
            slippage_breakdown = CostBreakdown(
                cost_type=CostType.SLIPPAGE,
                amount=slippage_cost,
                rate=slippage_result.slippage_rate,
                description=f"滑点成本: {slippage_result.slippage_rate:.4%}",
                calculation_details={
                    "slippage_amount": float(slippage_result.slippage_amount),
                    "slippage_rate": slippage_result.slippage_rate,
                    "model_type": slippage_result.model_type.value
                }
            )
        
        # 总成本
        total_cost = commission + transfer_fee + slippage_cost
        total_rate = float(total_cost / market_value) if market_value > 0 else 0.0
        
        # 成本明细
        cost_breakdown = [commission_breakdown, transfer_fee_breakdown]
        if slippage_breakdown:
            cost_breakdown.append(slippage_breakdown)
        
        return TransactionCost(
            order_id=order.order_id,
            symbol=order.symbol,
            side=order.side,
            quantity=quantity,
            price=price,
            market_value=market_value,
            commission=commission,
            transfer_fee=transfer_fee,
            slippage_cost=slippage_cost,
            total_cost=total_cost,
            total_rate=total_rate,
            cost_breakdown=cost_breakdown
        )


class TransactionCostAnalyzer:
    """
    交易成本分析器
    
    提供交易成本计算、分析和优化功能。
    """
    
    def __init__(self):
        """初始化交易成本分析器"""
        self._models: Dict[MarketType, BaseCostModel] = {}
        self._register_default_models()
        self._cost_history: List[TransactionCost] = []
    
    def _register_default_models(self) -> None:
        """注册默认成本模型"""
        self._models[MarketType.A_SHARE] = AShareCostModel()
        self._models[MarketType.FUTURES] = FuturesCostModel()
        self._models[MarketType.ETF] = ETFCostModel()
    
    def register_model(self, market_type: MarketType, model: BaseCostModel) -> None:
        """注册成本模型"""
        self._models[market_type] = model
    
    def calculate_cost(
        self,
        order: Order,
        market_type: MarketType,
        fill: Optional[OrderFill] = None,
        slippage_result: Optional[SlippageResult] = None
    ) -> TransactionCost:
        """
        计算交易成本
        
        Args:
            order: 订单信息
            market_type: 市场类型
            fill: 成交信息
            slippage_result: 滑点结果
            
        Returns:
            TransactionCost: 交易成本
        """
        if market_type not in self._models:
            raise ValueError(f"Unsupported market type: {market_type}")
        
        model = self._models[market_type]
        cost = model.calculate_cost(order, fill, slippage_result)
        
        # 记录成本历史
        self._cost_history.append(cost)
        
        return cost
    
    def get_model(self, market_type: MarketType) -> Optional[BaseCostModel]:
        """获取成本模型"""
        return self._models.get(market_type)
    
    def analyze_costs(
        self,
        costs: Optional[List[TransactionCost]] = None,
        start_date: Optional[datetime] = None,
        end_date: Optional[datetime] = None
    ) -> Dict[str, Any]:
        """
        分析交易成本
        
        Args:
            costs: 成本列表（如果为None则使用历史记录）
            start_date: 开始日期
            end_date: 结束日期
            
        Returns:
            Dict[str, Any]: 成本分析结果
        """
        if costs is None:
            costs = self._cost_history
        
        # 日期过滤
        if start_date or end_date:
            filtered_costs = []
            for cost in costs:
                if start_date and cost.calculated_at < start_date:
                    continue
                if end_date and cost.calculated_at > end_date:
                    continue
                filtered_costs.append(cost)
            costs = filtered_costs
        
        if not costs:
            return {}
        
        # 基础统计
        total_trades = len(costs)
        total_market_value = sum(float(cost.market_value) for cost in costs)
        total_cost = sum(float(cost.total_cost) for cost in costs)
        avg_cost_rate = total_cost / total_market_value if total_market_value > 0 else 0
        
        # 按成本类型分析
        cost_by_type = {}
        for cost in costs:
            for breakdown in cost.cost_breakdown:
                cost_type = breakdown.cost_type.value
                if cost_type not in cost_by_type:
                    cost_by_type[cost_type] = {"amount": 0.0, "count": 0}
                cost_by_type[cost_type]["amount"] += float(breakdown.amount)
                cost_by_type[cost_type]["count"] += 1
        
        # 按买卖方向分析
        buy_costs = [cost for cost in costs if cost.side == OrderSide.BUY]
        sell_costs = [cost for cost in costs if cost.side == OrderSide.SELL]
        
        buy_total_cost = sum(float(cost.total_cost) for cost in buy_costs)
        sell_total_cost = sum(float(cost.total_cost) for cost in sell_costs)
        buy_total_value = sum(float(cost.market_value) for cost in buy_costs)
        sell_total_value = sum(float(cost.market_value) for cost in sell_costs)
        
        # 成本率分布
        cost_rates = [cost.total_rate for cost in costs]
        cost_rates.sort()
        
        return {
            "summary": {
                "total_trades": total_trades,
                "total_market_value": total_market_value,
                "total_cost": total_cost,
                "avg_cost_rate": avg_cost_rate,
                "min_cost_rate": min(cost_rates) if cost_rates else 0,
                "max_cost_rate": max(cost_rates) if cost_rates else 0,
                "median_cost_rate": cost_rates[len(cost_rates) // 2] if cost_rates else 0
            },
            "by_cost_type": cost_by_type,
            "by_side": {
                "buy": {
                    "count": len(buy_costs),
                    "total_cost": buy_total_cost,
                    "total_value": buy_total_value,
                    "avg_cost_rate": buy_total_cost / buy_total_value if buy_total_value > 0 else 0
                },
                "sell": {
                    "count": len(sell_costs),
                    "total_cost": sell_total_cost,
                    "total_value": sell_total_value,
                    "avg_cost_rate": sell_total_cost / sell_total_value if sell_total_value > 0 else 0
                }
            },
            "cost_distribution": {
                "percentiles": {
                    "p10": cost_rates[int(len(cost_rates) * 0.1)] if cost_rates else 0,
                    "p25": cost_rates[int(len(cost_rates) * 0.25)] if cost_rates else 0,
                    "p50": cost_rates[int(len(cost_rates) * 0.5)] if cost_rates else 0,
                    "p75": cost_rates[int(len(cost_rates) * 0.75)] if cost_rates else 0,
                    "p90": cost_rates[int(len(cost_rates) * 0.9)] if cost_rates else 0
                }
            }
        }
    
    def optimize_execution(
        self,
        order: Order,
        market_type: MarketType,
        execution_strategies: List[str]
    ) -> Dict[str, Any]:
        """
        优化执行策略以降低交易成本
        
        Args:
            order: 订单信息
            market_type: 市场类型
            execution_strategies: 执行策略列表
            
        Returns:
            Dict[str, Any]: 优化建议
        """
        # 这里可以实现更复杂的成本优化逻辑
        # 比如分析不同执行策略的预期成本
        
        recommendations = []
        
        # 基于订单大小的建议
        if order.quantity > Decimal("10000"):
            recommendations.append("建议使用TWAP或VWAP策略分批执行大单")
        
        # 基于市场类型的建议
        if market_type == MarketType.A_SHARE:
            recommendations.append("A股交易建议避开开盘和收盘时段以减少滑点")
        elif market_type == MarketType.FUTURES:
            recommendations.append("期货交易建议关注持仓量和成交量变化")
        
        return {
            "order_analysis": {
                "order_id": order.order_id,
                "symbol": order.symbol,
                "quantity": float(order.quantity),
                "estimated_value": float(order.quantity * (order.price or Decimal("0")))
            },
            "recommendations": recommendations,
            "suggested_strategies": execution_strategies[:3]  # 推荐前3个策略
        }
    
    def get_cost_history(
        self,
        symbol: Optional[str] = None,
        start_date: Optional[datetime] = None,
        end_date: Optional[datetime] = None
    ) -> List[TransactionCost]:
        """获取成本历史记录"""
        costs = self._cost_history
        
        # 标的过滤
        if symbol:
            costs = [cost for cost in costs if cost.symbol == symbol]
        
        # 日期过滤
        if start_date:
            costs = [cost for cost in costs if cost.calculated_at >= start_date]
        if end_date:
            costs = [cost for cost in costs if cost.calculated_at <= end_date]
        
        return costs
    
    def clear_history(self) -> None:
        """清空成本历史记录"""
        self._cost_history.clear()


# 成本模型别名，用于向后兼容
CostModel = TransactionCostAnalyzer